

#ifndef MYWINDOW_H
#define MYWINDOW_H

#include <iostream>

//#include <Windows.h>
#include <memory>
#include <cmath>

#include <SDL2/SDL.h>
#include <SDL2/SDL_video.h>

#include "signalslot.h"

#include "GLRenderer.h"

//#include "Camera.h"

const float W_CORNER_PAD = 12.0f;

const float FONT_TEX_SIZE = 1024.0f;

#define NULL_BUFF 0

extern int dummy_zone[2];

const float paddings[] = {
        15, 16, 18, 33, 28, 43, 38, 12, 16, 16, 22, 36, 12, 22, 12, 20,
        28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 12, 12, 36, 36, 36, 24,
        52, 35, 30, 34, 37, 28, 26, 37, 37, 12, 18, 29, 25/*35*/, 46, 39, 42,
        30, 41, 31, 27, 28, 36, 33, 49, 31, 30, 31, 16, 20, 16, 36, 23,
        14, 27, 31, 24, 31, 28, 15, 31, 29, 11, 11, 24, 11, 45, 29, 31,
        31, 31, 18, 21, 16, 29, 25, 37, 23, 25, 26, 16, 12, 16, 36, 40,//36,
        38, 24, 12, 19, 18, 37, 20, 20, 28, 64, 54, 17, 55, 29, 38, 37,
        31, 12, 12, 18, 18, 22, 28, 55, 36, 43, 43, 17, 45, 24, 30, 30,
        15, 29, 29, 18, 31, 25, 12, 25, 28, 48, 31, 26, 36, 22, 48, 12,
        21, 36, 12, 11, 20, 30, 26, 12, 28, 62, 25, 26, 11, 27, 21, 11,
        35, 30, 30, 24, 36, 28, 45, 30, 39, 39, 29, 36, 45, 37, 42, 37,
        30, 34, 28, 29, 39, 31, 39, 34, 48, 49, 38, 41, 30, 34, 53, 31,
        27, 30, 26, 19, 29, 28, 37, 25, 30, 30, 24, 28, 35, 30, 31, 30,
        31, 24, 20, 25, 35, 23, 31, 29, 41, 42, 30, 36, 25, 25, 43, 27,
};

enum { LEFT = 1, RIGHT, TOP, BOTTOM };

const float WF_COORDS[][8] =	{{0.08f, 1-0.08f, 0.08f, 1-0.45f, 0.46f, 1-0.04f, 0.46f, 1-0.45f},
								 {0.58f, 1-0.04f, 0.58f, 1-0.46f, 0.96f, 1-0.08f, 0.96f, 1-0.46f},
								 {0.58f, 0.42f, 0.58f, 0.08f, 0.96f, 0.42f, 0.96f, 0.08f},
								 {0.08f, 0.42f, 0.08f, 0.08f, 0.46f, 0.42f, 0.46f, 0.08f}};


const float WI_COORDS[2][8] =	{{0.0f, 0.128f, 0.0f, 0.08f, 0.128f, 0.128f, 0.128f, 0.0f},
								{0.58f, 1-0.04f, 0.58f, 1-0.46f, 0.96f, 1-0.04f, 0.96f, 1-0.46f}};

//static const int MAX_CONSOLE_LINES = 50;

extern GLTexture ui_texture1;
extern GLTexture ui_texture2;
extern GLTexture font_texture;


//void RedirectIOToConsole();


//static void InitWndClass();

class MyRect{
public:
	int left, right, top, bottom;
};

void GetWindowRect(SDL_Window* window, MyRect& window_rect);

class MyWinFrame {

	float positions_[84];
	float tex_coords_[56];
	float dims_[4];

public:
	MyWinFrame(){}
	MyWinFrame(float start_x, float start_y, float width, float height, int skin, int zone_size[2]);
	~MyWinFrame(){};

	void UpdateSize(int new_size[2]);
	void UpdateSize(float start_x, float start_y, float width, float height, int zone_size[2]);

	void Draw();
};


class MyBaseElement {

protected:

	float dims_[4];
	int dims_px_[4];

	bool resizable_;

public:
	MyBaseElement(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);
	MyBaseElement();
	virtual ~MyBaseElement();

	inline const float* dims() { return dims_;}
	inline const int* dims_px() { return dims_px_;}
	inline bool resizable(){ return resizable_; }

	void Resize(int zone_size[2]);
	virtual void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);

	virtual void Draw() = 0;

	virtual bool Check(float x, float y);
};

class MyTypeMesh : public MyBaseElement {
	
	std::string text_;
	std::vector<float> positions_;
	std::vector<float> tex_coords_;
	int num_tris_;

	float center_x_, center_y_;
	float scale_;

public:
	MyTypeMesh(std::string text, float start_x, float start_y, float scale, int zone_size[2]);
	MyTypeMesh();
	MyTypeMesh(const MyTypeMesh& mesh_to_copy);
	~MyTypeMesh();

	inline std::vector<float>* positions(){ return &positions_; }
	inline std::string text(){return text_;}

	void Draw();

	void Move(float new_x, float new_y, int zone_size[2]);
	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);
	void Centrate();
	bool Check(float x, float y);
};



class MyLinearLayout : public MyBaseElement {
protected:
	std::vector< MyBaseElement* > elements_;

	bool vertical_;

public:
	//MyLinearLayout(){}
	MyLinearLayout(float start_x, float start_y, float size_x, float size_y, int zone_size[2], bool vertical)
		: MyBaseElement(start_x, start_y, size_x, size_y, zone_size),
		  vertical_(vertical)
	{
	}
	MyLinearLayout(bool vertical)
		: MyBaseElement(0, 0, 500, 500, dummy_zone),
		  vertical_(vertical)
	{
	}
	~MyLinearLayout() {

	}

	inline void set_vertical(bool val) {
		vertical_ = val;
	}

	void AddElement(MyBaseElement* element) {
		
		elements_.push_back(element);

	}

	void InsertElement(MyBaseElement* element, unsigned int pos) {

		elements_.insert(elements_.begin() + pos, element);

	}

	void ReplaceElement(MyBaseElement* element, unsigned int pos) {

		if(pos == elements_.size())
		{
			elements_.push_back(element);
		} else
		{
			elements_[ pos ] = element;
		}

	}
	/*
	void ChangeElement(MyBaseElement* element, int pos) {

		elements_[ pos ] = element;
	}
	*/
	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);

	bool Check(float x, float y)
	{
		for(auto element = elements_.begin(); element != elements_.end(); element++)
		{
			if((*element)->Check(x, y))
			{
				//std::cout << "check is true" << std::endl;
				return true;
			}
		}
		//std::cout << "check is false" << std::endl;
		return false;
	}

	void Draw() {

		for(auto element = elements_.begin(); element != elements_.end(); element++)
		{
			(*element)->Draw();
		}

	}
};

enum{	INTEGERS	=	1,
		CHARS		=	2,
		FLOATS		=	4,
		SIGNED		=	8,
		MULTILINE	=	16	};



class MyEditBox : public MyBaseElement {

	//std::unique_ptr< MyLinearLayout > box_;
	MyLinearLayout box_;
	std::vector< MyTypeMesh > lines_;
	//std::unique_ptr< MyTypeMesh> cursor_;
	MyTypeMesh cursor_;
	std::vector< std::string > lines_text_;
	int current_line_;
	unsigned int current_char_;
	float scale_;
	int zone_size_[2];
	//bool multiline_;
	bool focused_;


	union {
		char set				:	8;
		struct{
			bool int_allowed	:	1;
			bool char_allowed	:	1;
			bool float_allowed	:	1;
			bool signed_allowed	:	1;
			bool multiline		:	1;
		};
	}flags_;

	//std::unique_ptr< MyWinFrame > back_;
	MyWinFrame back_;

public:
	//MyEditBox(){}
	MyEditBox(std::string text, float start_x, float start_y, float size_x, float size_y, float scale, int zone_size[2], char flags);
	~MyEditBox() {

	}

	std::string GetLine(int line);

	bool focused(){return focused_;}

	void set_focus(bool focus){focused_ = focus;}

	void Clear();
	void AddLine(std::string text);
	void DeleteLine(int line);
	void InsertLine(std::string text);
	void Listen(std::vector<unsigned char>& keys);
	void AddChar(unsigned char s);
	void DeleteChar();
	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);
	bool Check(float x, float y);
	void Draw();

};


class MyButton : public MyBaseElement {

protected:

	cSignal< int > press_signal_;

	MyWinFrame button_frame_;
	MyWinFrame button_frame_pressed_;

	MyTypeMesh text_;

	bool pressed_;

public:
	MyButton() : pressed_(false){}
	MyButton(std::string text, float start_x = 0.0f, float start_y = 0.0f, float size_x = 0.1f, float size_y = 0.1f, int zone_size[2] = dummy_zone);

	~MyButton() {
	}

	MyButton(const MyButton& other) : press_signal_(other.press_signal_),
								button_frame_(other.button_frame_),
								button_frame_pressed_(other.button_frame_pressed_),
								text_(other.text_),
								pressed_(other.pressed_){

	}

	inline bool pressed() { return pressed_; }

	inline cSignal< int >& press_signal(){ return press_signal_;}

	inline void set_pressed(bool pressed) {
		pressed_ = pressed;
	}

	bool Check(float x, float y);
	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);
	void Draw();

};

class SignalSet{
public:
	cSignal< int, float, float > click_signal;
	cSignal< int, float, float > right_click_signal;
	cSignal< int, float, float > move_signal;
	cSignal< int, float, float > release_signal;
	cSignal< int, std::vector<unsigned char>& > key_press_signal;
	cSignal< int, bool > wheel_signal;
};

class MyGLView;

const float full_dims[] = {-1.0f, -1.0f, 2.0f, 2.0f};

enum {	FULL_SCR_ENABLED	=	1,
		MINIMIZABLE			=	2,
		CLOSABLE			=	4,
		RESIZABLE			=	8,
		BLUR_BEHIND			=	16	};

const char NORMAL_WINDOW = FULL_SCR_ENABLED | MINIMIZABLE | CLOSABLE | RESIZABLE;

class MyBaseWindow {

	union {
		char set	:	8;
		struct {
			bool full_scr_enabled	:	1;
			bool minimize_enabled	:	1;
			bool close_enabled		:	1;
			bool resize_enabled		:	1;
			bool blur_behind		:	1;
		};
	} flags_;

	void Init(std::string title);

protected:

	MyTypeMesh title_;
	MyWinFrame frame_;
	float dims_[4];

	SDL_Window* window_;
	MyRect window_rect_, wnd_rect_bfr_max_;

	int window_size_[2];

	bool drag_enabled_;
	bool update_needed_;
	float drag_zone_[4];
	float resize_zone_left_[4];
	float resize_zone_right_[4];
	float resize_zone_bottom_[4];
	float resize_zone_top_[4];
	int resize_;
	bool hidden_;

	MyButton close_button_;
	MyButton full_scr_button_;
	MyButton max_min_button_;

	//std::string class_name_;

	static SDL_GLContext shared_gl_context;

public:

	cSlot< MyBaseWindow, int, float, float > click;
	cSlot< MyBaseWindow, int, float, float > move;
	cSlot< MyBaseWindow, int, float, float > release;
	cSlot< MyBaseWindow, int, std::vector<unsigned char>& > key_press;

	cSlot< MyBaseWindow, int > quit;
	cSlot< MyBaseWindow, int > full_scr;
	cSlot< MyBaseWindow, int > minimize;
/*
	MyBaseWindow(std::string title, HWND window_handle, char flags = NORMAL_WINDOW) : window_handle_(window_handle){

		Init(title);

		flags_.set = flags;
	}
*/
	MyBaseWindow(std::string title, int size_x, int size_y, char flags);

	virtual ~MyBaseWindow(){

		//DestroyWindow(window_handle_);
		SDL_DestroyWindow(window_);
		if(shared_gl_context)
		{
			SDL_GL_DeleteContext(shared_gl_context);
		}

		//delete frame_;
	}

	MyRect window_rect(){ return window_rect_; }

	const int* window_size(){ return window_size_; }

	//HWND window_handle(){ return window_handle_; }
	SDL_Window* window(){return window_;}

	bool focused(){
		unsigned int flags =  SDL_GetWindowFlags(window_);
		return flags & SDL_WINDOW_INPUT_FOCUS;
	}

	bool hidden(){return hidden_;}

	virtual void Draw();

	void MakeCurrent() {
		//wglMakeCurrent(device_handle_, gl_context_handle_);
		SDL_GL_MakeCurrent(window_, shared_gl_context);
		Renderer::SetViewport(0, 0, window_size_[0], window_size_[1]);
	}

	void SetTopMost();

	void Apply() {
		//SwapBuffers (device_handle_);
		SDL_GL_SwapWindow(window_);
	}

	void Hide() {
		//ShowWindow(window_handle_, SW_HIDE);
		hidden_ = true;
		SDL_HideWindow(window_);
	}

	void Show() {
		//ShowWindow(window_handle_, SW_SHOW);
		hidden_ = false;
		SDL_ShowWindow(window_);
	}

	void Connect(SignalSet& signals){
		click.Connect(signals.click_signal);
		move.Connect(signals.move_signal);
		release.Connect(signals.release_signal);
		key_press.Connect(signals.key_press_signal);
	}

	virtual int OnClick(float x, float y);
	virtual int OnMove(float dx, float dy);
	virtual int OnRelease(float x, float y);
	virtual int OnKeyPress(std::vector<unsigned char>& keys) {
		if(!focused())
		{
			return -1;
		}
		return 0;
	}

	virtual int Quit() {
		SDL_HideWindow(window_);
		return 0;
	}

	int Minimize() {
		SDL_MinimizeWindow(window_);
		return 0;
	}

	int GoFullScreen();


};

class MyDropMenu : public MyTypeMesh {

	bool draw_items_;
	std::vector< MyTypeMesh > items_;
	float scale_;
	int zone_size_[2];
	std::vector< cSignal< int > > signals_;

	MyWinFrame back_;
	float max_x_;

public:
	MyDropMenu (std::string text, float start_x, float start_y, float scale, int zone_size[2]);

	MyDropMenu (std::string text, float scale) :	MyTypeMesh(text, 0.0f, 0.0f, scale, dummy_zone),
													back_(0.0f, 0.0f, 0.0f, 0.0f, 1, dummy_zone),
													scale_(scale),
													draw_items_(false),
													max_x_(500){
		zone_size_[0] = 500;
		zone_size_[1] = 500;
	}

	
	~MyDropMenu() {

	}

	template < class T >
	void AddItem(std::string name, cSlot< T, int > &slot) {

		float free_place_y = dims_[1];
		if(!items_.empty())
		{
			free_place_y = items_.back().dims()[1];

			//cout << items_.back().dims()[1] << endl;
			//system("pause");
		}


		free_place_y -= (64.0f*scale_ * (700.0f / zone_size_[1]))/FONT_TEX_SIZE;

		MyTypeMesh new_item(name, dims_[0], free_place_y, scale_, zone_size_);

		if(new_item.dims()[2] > max_x_)
		{
			max_x_ = new_item.dims()[2];
		}

		items_.push_back(new_item);
		cSignal< int > new_signal;
		new_signal.Connect(slot);
		signals_.push_back(new_signal);

	}

	bool Check(float x, float y);
	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);
	void Draw() {
		MyTypeMesh::Draw();
		if(draw_items_)
		{
			back_.Draw();
			for(auto item = items_.begin(); item != items_.end(); item++)
			{
				(*item).Draw();
			}
		}
	}

};

static int dummy_zone22[2] = {100, 100};

class MyGLView : public MyBaseElement{

	GLuint framebuffer_;
	GLuint color_texture_;
	GLuint depth_texture_;

	float positions_[12];
	float tex_coords_[8];

public:
	MyGLView(float start_x = 0.0f, float start_y = 0.0f, float size_x = 1.0f, float size_y = 1.0f, int zone_size[2] = dummy_zone22);
	MyGLView(const MyGLView& view);

	~MyGLView() {
		glDeleteFramebuffers(1, &framebuffer_);
		glDeleteTextures(1, &color_texture_);
		glDeleteTextures(1, &depth_texture_);
	}

	void SetActive() {
		Renderer::set_draw_zone(0, 0, dims_px_[2], dims_px_[3]);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_);
	}

	virtual void Draw() {
		Renderer::SwitchOwnTexture(DIFFUSEMAP_SLOT, color_texture_);
		
		glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));
		glVertexAttribPointer(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE), 3, GL_FLOAT, GL_FALSE, 0, positions_);
		
		glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
		glVertexAttribPointer(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE), 2, GL_FLOAT, GL_FALSE, 0, tex_coords_);

		glDrawArrays(GL_QUADS, 0, 4);
		Renderer::CheckGLError("glDrawArrays");

		glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
		glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));

		//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, NULL);
	}

	virtual void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);

};

class MyIcon : public MyBaseElement {

	float positions_[12];
	float tex_coords_[8];

public:
	MyIcon(float start_x, float start_y, float size_x, float size_y, int icon, int zone_size[2]);

	~MyIcon(){}

	void Draw() {

		Renderer::SwitchTexture(DIFFUSEMAP_SLOT, ui_texture2);

		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);

		glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));
		glVertexAttribPointer(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE), 3, GL_FLOAT, GL_FALSE, 0, positions_);
		
		glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
		glVertexAttribPointer(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE), 2, GL_FLOAT, GL_FALSE, 0, tex_coords_);
	
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
		glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));

		glDisable(GL_BLEND);

	}

};

class MyEditField : public MyBaseElement {

	MyTypeMesh name_;
	MyEditBox edit_box_;

public:
	MyEditField(std::string name, char flags);
	~MyEditField();

	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]);
	void Draw();

	std::string GetValue();
	void SetValue(std::string);

	bool Check(float x, float y);

	void Accept();

	void Listen(std::vector<unsigned char>& keys);


	cSignal< int, std::string > changed_signal;
};

class MyListView : public MyLinearLayout {

	std::vector<MyTypeMesh> type_meshes_;
	float scale_, offset_;
	MyWinFrame cursor_, back_;
	int sel_item_, zone_[2], list_pos_, fit_items_;

	MyButton up_btn_, down_btn_;

public:
	cSignal<int, int, std::string> item_click;
	MyListView(float start_x = 0.0f, float start_y = 0.0f, float size_x = 0.1f, float size_y = 0.1f, float scale = 1.0f, int zone[2] = dummy_zone)
				: MyLinearLayout(start_x, start_y, size_x, start_y, zone, true),
				  cursor_(start_x, start_y, size_x, start_y, 3, zone),
				  back_(start_x, start_y, size_x, start_y, 1, zone),
				  scale_(scale),
				  offset_(0.0f),
				  sel_item_(-1),
				  list_pos_(0),
				  up_btn_("^", dims_[0] + dims_[2] - 48.0f/zone[0], dims_[1] + dims_[3] - 48.0f/zone[1], 48.0f/zone[0], 48.0f/zone[1], zone),
				  down_btn_("v", dims_[0] + dims_[2] - 48.0f/zone[0], dims_[1], 48.0f/zone[0], 48.0f/zone[1], zone){

		zone_[0] = zone[0];
		zone_[1] = zone[1];

		fit_items_ = dims_[3]/((40.0f*scale * (700.0f / zone_[1]))/FONT_TEX_SIZE);

		scroll_up_slot.AssignFunction(this, &MyListView::ScrollUp);
		scroll_down_slot.AssignFunction(this, &MyListView::ScrollDown);
		scroll_up_slot.Connect(up_btn_.press_signal());
		scroll_down_slot.Connect(down_btn_.press_signal());
	}
	cSignal<int, int, std::string> apply_signal;

	void AddElement(MyBaseElement* element){
		assert(false);
	}

	void AddElement(std::string element){
		type_meshes_.emplace_back(element, 0.0f, 0.0f, scale_, dummy_zone);
		elements_.clear();
		elements_.reserve(fit_items_);
		//for(auto& mesh : type_meshes_)
		int num = type_meshes_.size();
		num = fit_items_ < num ? fit_items_ : num;
		for(int i = list_pos_; i < list_pos_ + num; i++)
		{
			elements_.push_back(&type_meshes_[i]);
		}
	}

	void Clear(){
		type_meshes_.clear();
		elements_.clear();
	}

	virtual bool Check(float x, float y){
		if(!MyBaseElement::Check(x, y))
		{
			return false;
		}
		static bool hold = false;

		int list_pos_bfr = list_pos_;
		bool skip = false;
		if(down_btn_.Check(x, y) || up_btn_.Check(x, y))
		{
			skip = true;
		}

		if(list_pos_bfr != list_pos_)
		{
			int num = type_meshes_.size() - list_pos_;
			num = fit_items_ < num ? fit_items_ : num;
			elements_.clear();
			elements_.reserve(fit_items_);
			for(int i = list_pos_; i < list_pos_ + num; i++)
			{
				elements_.push_back(&type_meshes_[i]);
			}
			MyLinearLayout::Resize(dims_[0], dims_[1], dims_[2], dims_[3], zone_);
			ResizeCursor(zone_);
			return true;
		}

		if(skip)
		{
			return false;
		}

		hold = !hold;

		//static unsigned int last_time = 0;
		for(int i = 0; i < elements_.size(); i++)
		{
			const float* dims = elements_[i]->dims();
			if(y > dims[1]-0.015*scale_ && y < dims[1] + dims[3]+0.015*scale_)
			{
				if(/*SDL_GetTicks() - last_time < 300 && */sel_item_ == i && !hold)
				{
					item_click.Fire(i, type_meshes_[list_pos_ + i].text());
				}
				sel_item_ = i;
				ResizeCursor(zone_);
				return true;
			}
		}

		return false;
	}

	cSlot<MyListView, int> scroll_up_slot;
	int ScrollUp(){
		std::cout << "up" << std::endl;
		list_pos_--;
		list_pos_ = list_pos_ < 0 ? 0 : list_pos_;
		return 0;
	}

	cSlot<MyListView, int> scroll_down_slot;
	int ScrollDown(){
		std::cout << "down" << std::endl;
		list_pos_++;
		int n = list_pos_ >= type_meshes_.size() - elements_.size() ? type_meshes_.size() - elements_.size() : list_pos_;
		list_pos_ = n < 0 ? 0 : n;
		return 0;
	}

	void Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]){

		zone_[0] = zone_size[0];	zone_[1] = zone_size[1];

		fit_items_ = (size_y-8.0f/zone_size[1])/(8.0f/zone_size[1] + (40.0f*scale_ * (700.0f / zone_size[1]))/FONT_TEX_SIZE);
		int num = type_meshes_.size() - list_pos_;
		num = fit_items_ < num ? fit_items_ : num;
		elements_.clear();
		elements_.reserve(fit_items_);
		for(int i = list_pos_; i < list_pos_ + num; i++)
		{
			elements_.push_back(&type_meshes_[i]);
		}

		up_btn_.Resize(start_x + size_x - 48.0f/zone_size[0], start_y + size_y - 48.0f/zone_size[1], 48.0f/zone_size[0], 48.0f/zone_size[1], zone_size);
		down_btn_.Resize(start_x + size_x - 48.0f/zone_size[0], start_y, 48.0f/zone_size[0], 48.0f/zone_size[1], zone_size);

		back_.UpdateSize(start_x, start_y, size_x, size_y, zone_size);

		MyLinearLayout::Resize(start_x + 4.0f/zone_size[0], start_y, size_x, size_y, zone_size);
		ResizeCursor(zone_size);
	}

	void ResizeCursor(int zone_size[2]){
		if(sel_item_ != -1)
		{
			sel_item_ = sel_item_ >= elements_.size() ? elements_.size()-1 : sel_item_;
			const float* dims = elements_[sel_item_]->dims();
			cursor_.UpdateSize(dims_[0], dims[1]-4.0f/zone_size[1], dims_[2], dims[3]+8.0f/zone_size[1], zone_size);
		}
	}

	void Draw(){
		glScissor(dims_px_[0], dims_px_[1], dims_px_[2], dims_px_[3]);
		glEnable(GL_SCISSOR_TEST);
		back_.Draw();
		if(sel_item_ != -1)
		{
			cursor_.Draw();
		}
		MyLinearLayout::Draw();

		if(fit_items_ < type_meshes_.size())
		{
			up_btn_.Draw();
			down_btn_.Draw();
		}
		glDisable(GL_SCISSOR_TEST);
	}



};


class MouseMove {
public:
	float x, y;
};


extern MouseMove current_mouse;
extern MouseMove prev_mouse;

extern bool g_quit;

void ForceWindowUpdate();

bool FireSignals(cSignal<int, float, float>& click_signal, cSignal<int, float, float>& release_signal, cSignal<int, float, float>& move_signal, cSignal< int, std::vector<unsigned char>& >& key_press_signal, cSignal<int, float, float>* right_click_signal = nullptr, cSignal<int, bool>* wheel_signal = nullptr, bool wait = false);

//bool FireSignals(HWND hWnd, unsigned int message, WPARAM wParam, cSignal<int, float, float>& click_signal, cSignal<int, float, float>& release_signal, cSignal<int, float, float>& move_signal);

#endif
